home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
explode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-16
|
7KB
|
239 lines
/* SCCS Id: @(#)explode.c 3.1 90/11/06
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
/* Note: Arrays are column first, while the screen is row first */
static int expl[3][3] =
{ S_explode1, S_explode4, S_explode7,
S_explode2, S_explode5, S_explode8,
S_explode3, S_explode6, S_explode9 };
/* Note: I had to choose one of three possible kinds of "type" when writing
* this function: a wand type (like in zap.c), an adtyp, or an object type.
* Wand types get complex because they must be converted to adtyps for
* determining such things as fire resistance. Adtyps get complex in that
* they don't supply enough information--was it a player or a monster that
* did it, and with a wand, spell, or breath weapon? Object types share both
* these disadvantages....
*/
void
explode(x, y, type, dam, olet)
int x, y;
int type; /* the same as in zap.c */
int dam;
char olet;
{
int i, j, k;
boolean starting = 1;
boolean visible, any_shield;
int uhurt = 0; /* 0=unhurt, 1=items damaged, 2=you and items damaged */
const char *str;
int idamres, idamnonres;
struct monst *mtmp;
uchar adtyp;
int explmask[3][3];
/* 0=normal explosion, 1=do shieldeff, 2=do nothing */
boolean shopdamage = FALSE;
switch(abs(type) % 10) {
default: impossible("explosion base type %d?", type); return;
case 1: str = (olet == SCROLL_CLASS ? "tower of flame" : "fireball"); adtyp = AD_FIRE; break;
/* case 3: str = "ball of cold"; adtyp = AD_COLD; break; */
/* case 5: str = "ball lightning"; adtyp = AD_ELEC; break; */
/* case 7: str = "acid ball"; adtyp = AD_ACID; break; */
}
any_shield = visible = FALSE;
for(i=0; i<3; i++) for(j=0; j<3; j++) {
if (!isok(i+x-1, j+y-1)) {
explmask[i][j] = 2;
continue;
}
if (i+x-1 == u.ux && j+y-1 == u.uy) {
switch(adtyp) {
case AD_FIRE:
explmask[i][j] = Fire_resistance ? 1 : 0;
break;
/* case AD_COLD: */
/* case AD_ELEC: */
/* case AD_DISN: */
/* case AD_ACID: */
default:
impossible("explosion type %d?", adtyp);
explmask[i][j] = 0;
break;
}
}
/* can be both you and mtmp if you're swallowed */
if (mtmp = m_at(i+x-1, j+y-1)) {
switch(adtyp) {
case AD_FIRE:
explmask[i][j] = resists_fire(mtmp->data)
? 1 : 0;
break;
/* case AD_COLD: */
/* case AD_ELEC: */
/* case AD_DISN: */
/* case AD_ACID: */
default:
impossible("explosion type %d?", adtyp);
explmask[i][j] = 0;
break;
}
} else if (i+x-1 != u.ux || j+j-1 != u.uy)
explmask[i][j] = 0;
if (cansee(i+x-1, j+y-1)) visible = TRUE;
if (explmask[i][j] == 1) any_shield = TRUE;
}
if (visible) {
/* Start the explosion */
for(i=0; i<3; i++) for(j=0; j<3; j++) {
if (explmask[i][j] == 2) continue;
tmp_at(starting ? DISP_BEAM : DISP_CHANGE,
cmap_to_glyph(expl[i][j]));
tmp_at(i+x-1, j+y-1);
starting = 0;
}
curs_on_u(); /* will flush screen and output */
if (any_shield) { /* simulate a shield effect */
for (k = 0; k < SHIELD_COUNT; k++) {
for(i=0; i<3; i++) for(j=0; j<3; j++) {
if (explmask[i][j] == 1)
/*
* Bypass tmp_at() and send the shield glyphs
* directly to the buffered screen. tmp_at()
* will clean up the location for us later.
*/
show_glyph(i+x-1, j+y-1,
cmap_to_glyph(shield_static[k]));
}
curs_on_u(); /* will flush screen and output */
delay_output();
}
/* Cover last shield glyph with blast symbol. */
for(i=0; i<3; i++) for(j=0; j<3; j++) {
if (explmask[i][j] == 1)
show_glyph(i+x-1,j+y-1,cmap_to_glyph(expl[i][j]));
}
} else { /* delay a little bit. */
delay_output();
delay_output();
}
} else You("hear a blast.");
for(i=0; i<3; i++) for(j=0; j<3; j++) {
if (explmask[i][j] == 2) continue;
if (i+x-1 == u.ux && j+y-1 == u.uy)
uhurt = (explmask[i][j] == 1) ? 1 : 2;
idamres = idamnonres = 0;
(void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1),
type, &shopdamage);
mtmp = m_at(i+x-1, j+y-1);
if (!mtmp) continue;
if (u.uswallow && mtmp == u.ustuck) {
if (is_animal(u.ustuck->data))
pline("%s gets heartburn!",
Monnam(u.ustuck));
else
pline("%s gets toasted slightly!",
Monnam(u.ustuck));
} else
pline("%s is caught in the %s!",
cansee(i+x-1, j+y-1) ? Monnam(mtmp) : "It", str);
idamres += destroy_mitem(mtmp, SCROLL_CLASS, (int) adtyp);
idamres += destroy_mitem(mtmp, SPBOOK_CLASS, (int) adtyp);
/* Fire resistance protects monsters from burning scrolls, */
/* but not from exploding potions. */
idamnonres += destroy_mitem(mtmp, POTION_CLASS, (int) adtyp);
/*
idamnonres += destroy_mitem(mtmp, WAND_CLASS, (int) adtyp);
idamnonres += destroy_mitem(mtmp, RING_CLASS, (int) adtyp);
*/
if (explmask[i][j] == 1) {
golemeffects(mtmp, (int) adtyp, dam + idamres);
mtmp->mhp -= idamnonres;
} else {
/* call resist with 0 and do damage manually so 1) we can
* get out the message before doing the damage, and 2) we can
* call mondied, not killed, if it's not your blast
*/
int mdam = dam;
if (resist(mtmp, olet, 0, FALSE)) {
pline("%s resists the magical blast!",
cansee(i+x-1,j+y-1) ? Monnam(mtmp)
: "It");
mdam = dam/2;
}
if (mtmp == u.ustuck)
mdam *= 2;
if (resists_cold(mtmp->data) /* && adtyp == AD_FIRE */)
mdam *= 2;
mtmp->mhp -= mdam;
mtmp->mhp -= (idamres + idamnonres);
}
if (mtmp->mhp <= 0) {
if (type >= 0) killed(mtmp);
else mondied(mtmp);
}
}
if (visible) tmp_at(DISP_END, 0); /* clear the explosion */
/* Do your injury last */
if (uhurt) {
if (type >= 0 && flags.verbose && olet != SCROLL_CLASS)
You("are caught in the %s!", str);
if (uhurt == 2) u.uhp -= dam;
if (u.uhp <= 0) {
char buf[BUFSZ];
if (type >= 0 && olet != SCROLL_CLASS) {
killer_format = NO_KILLER_PREFIX;
Sprintf(buf, "caught %sself in %s own %s.",
flags.female ? "her" : "him",
flags.female ? "her" : "his", str);
} else {
killer_format = KILLED_BY;
Strcpy(buf, str);
}
killer = buf;
/* done(adtyp == AD_FIRE ? BURNING : DIED); */
done(BURNING);
}
exercise(A_STR, FALSE);
#if defined(POLYSELF)
ugolemeffects((int) adtyp, dam);
#endif
destroy_item(SCROLL_CLASS, (int) adtyp);
destroy_item(SPBOOK_CLASS, (int) adtyp);
destroy_item(POTION_CLASS, (int) adtyp);
/*
destroy_item(RING_CLASS, (int) adtyp);
destroy_item(WAND_CLASS, (int) adtyp);
*/
}
if (shopdamage) {
pay_for_damage("burn away");
/* (only if we ever add non-fire balls)
pay_for_damage(adtyp == AD_FIRE ? "burn away" :
adtyp == AD_COLD ? "shatter" :
adtyp == AD_DISN ? "disintegrate" : "destroy");
*/
}
}
/*explode.c*/